package com.jumper.study.front.websocket;

import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import com.jumper.study.admin.bo.AdminUserDetails;
import com.jumper.study.common.api.CommonResult;
import com.jumper.study.front.service.StudentLessonService;
import com.jumper.study.front.websocket.dto.MessageDto;

import cn.hutool.json.JSONUtil;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnError;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.ServerEndpoint;

@ServerEndpoint("/ws/study")
@Component
public class StudyWebSocketServer {
    private static final Logger LOGGER = LoggerFactory.getLogger(StudyWebSocketServer.class);

    private Session session;

    private Long accountId;

    private static final AtomicInteger onlineCount = new AtomicInteger(0);

    private static StudentLessonService studentLessonService;

    @Autowired
    public void setStudentLessonService(StudentLessonService studentLessonService) {
        StudyWebSocketServer.studentLessonService = studentLessonService;
    }

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        Authentication token = (Authentication)session.getUserPrincipal();
        AdminUserDetails detail = (AdminUserDetails)token.getPrincipal();
        accountId = detail.getAccount().getId();
        
        onlineCount.getAndIncrement();
        LOGGER.debug("student linked, accountId:{}, online:{}", detail.getAccount().getId(), onlineCount.get());
    }

    @OnClose
    public void onClose() {
        onlineCount.getAndDecrement();
        LOGGER.debug("student unlinked, accountId:{} online:{}", accountId, onlineCount.get());
    }

    @OnMessage
    public void onMessage(String message) {
        LOGGER.debug("msg src:{}", message);
        MessageDto dto = JSONUtil.toBean(message, MessageDto.class);
        LOGGER.debug("msg: {}", dto);
        switch(dto.getType()) {
            case START:
                startStudy(dto);
                break;
            case UPDATE:
                updateStudy(dto);
                break;
            case END:
                endStudy(dto);
                break;
            default:
                session.getAsyncRemote().sendText(JSONUtil.toJsonStr(CommonResult.success()));
                break;
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        LOGGER.error("websocket session:{}, error:{}", session, error);
    }

    public void startStudy(MessageDto msg) {
        boolean re = studentLessonService.reConnect(msg.getLessonId(), msg.getChapterId(), accountId);
        LOGGER.debug("is re:{}", re);
        if (!re) {
            studentLessonService.startStudy(msg.getLessonId(), msg.getChapterId(), accountId);
        }
    }

    public void updateStudy(MessageDto msg) {
        studentLessonService.updateStudy(msg.getLessonId(), msg.getChapterId(), accountId);
    }

    public void endStudy(MessageDto msg) {
        studentLessonService.endStudy(msg.getLessonId(), msg.getChapterId(), accountId);
    }
}
